import { existsSync } from 'fs'
import * as path from 'path'

/**
 * 寻找并返回当前路径以上最近的一个满足条件的目录路径。
 * @param currentPath 当前文件或目录的路径。
 * @param option 包含配置的对象，可以指定查找的深度和目录匹配条件。
 * @param option.depth 查找目录的最大深度，默认为2。
 * @param option.onDirectory 一个字符串或函数，用于判断目录是否满足条件。如果是字符串，直接匹配目录名；如果是函数，则传入目录路径，返回一个布尔值表示是否匹配。
 * @returns 符合条件的目录路径，如果未找到则返回null。
 */
export function closetDirectory(
  currentPath: string,
  option: {
    depth?: number
    onDirectory: string | ((directory: string) => boolean)
  }
): string | null {
  // 设置基础查找深度，如果未指定，则默认为2
  const anchorDepth = option.depth ?? 2
  let anchorCounter = 0 // 已查找的目录层数计数器
  // 确保路径是绝对路径
  currentPath = path.isAbsolute(currentPath) ? currentPath : path.resolve(__dirname, currentPath)

  /**
   * 根据条件判断目录是否有效。
   * @param anchorDir 当前检查的目录路径。
   * @returns 如果目录满足条件，返回true；否则，返回false。
   */
  const onDirectory = (anchorDir: string) =>
    typeof option.onDirectory === 'function'
      ? option.onDirectory(anchorDir)
      : existsSync(path.join(currentPath, option.onDirectory))

  // 循环向上查找，直到找到符合条件的目录或达到最大深度
  while (!onDirectory(currentPath)) {
    if (anchorCounter >= anchorDepth || currentPath == null || currentPath === '') {
      // 如果达到指定深度或路径无效，返回null
      return null
    }

    // 移动到上一级目录
    currentPath = path.dirname(currentPath)
    anchorCounter++ // 增加目录层数计数器
  }

  // 返回找到的目录路径
  return currentPath
}

/**
 * 寻找并返回当前路径以上最近的一个满足条件的目录路径，并拼接上原地址
 * @param currentPath
 * @param option
 * @returns
 */
export function closetTarget(
  currentPath: string,
  option: {
    depth?: number
    target: string
  }
): string | null {
  const anchorDirectory = closetDirectory(currentPath, {
    ...option,
    onDirectory: option.target,
  })

  return anchorDirectory
    ? path.isAbsolute(option.target)
      ? option.target
      : path.join(anchorDirectory, option.target)
    : null
}
